<template>
  <div class="hq-form">
    <el-form
      ref="hqFrom"
      class="hq-form_form"
      v-bind="mergeFormAttrs"
      :model="props.models"
      :rules="props.formRules"
    >
      <template v-for="field in props.fields" :key="field.prop">
        <el-form-item
          v-if="!field.oSlot"
          :prop="field.prop"
          :label="field.label"
          v-bind="field.attrs"
          :class="{ 'date-from-item': field?.attrs?.type === 'datetimerange' }"
        >
          <component
            :is="components[field.type]"
            v-if="!field.slot"
            :models="props.models"
            :field="field"
          ></component>
          <slot v-else :name="field.prop"></slot>
        </el-form-item>
        <slot v-else :name="field.prop"></slot>
      </template>
    </el-form>
    <div class="hq-form_action">
      <el-button
        v-if="mergeSubmitBtn.show"
        :type="mergeSubmitBtn.type"
        :size="mergeSubmitBtn.size"
        @click="onSubmit"
      >
        {{ mergeSubmitBtn.text }}
      </el-button>
      <el-button
        v-if="mergeResetBtn.show"
        :type="mergeResetBtn.type"
        :size="mergeResetBtn.size"
        @click="resetFields"
      >
        {{ mergeResetBtn.text }}
      </el-button>
      <slot name="actionBtn"></slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import components from './fields/index'
import { submitForm, resetForm } from '@/utils'
import { computed, ref, toRaw } from 'vue'
import { FormInstance, FormRules } from 'element-plus'
import { IBaseFieldItem } from './interface'

interface IButton {
  text?: string
  show?: boolean
  isReset?: boolean
  type?: '' | 'default' | 'info' | 'success' | 'warning' | 'primary' | 'danger'
  size?: '' | 'default' | 'small' | 'large'
}

interface IProps {
  fields: IBaseFieldItem[] // 表单数据
  models: Record<string, string | number> // 表单数据对象 v-model
  formAttrs?: Record<string, string | number | boolean> // 表单属性
  formRules?: FormRules // 校验规则
  submitBtn?: IButton // 提交按钮
  resetBtn?: IButton // 重置按钮
}
const props = withDefaults(defineProps<IProps>(), {
  formAttrs: () => ({}),
  formRules: () => ({}),
  submitBtn: () => ({}),
  resetBtn: () => ({})
})
const emit = defineEmits(['submit', 'error', 'reset'])
const hqFrom = ref<FormInstance | null>(null)

/**
 * 默认属性
 */
const mergeFormAttrs = computed(() => {
  return Object.assign({ inline: false, labelWidth: '120px' }, props.formAttrs)
})

/**
 * 重置按钮
 */
const mergeResetBtn = computed(() => {
  return Object.assign(
    { isReset: true, show: true, text: '提交', type: 'info', size: 'small' },
    props.resetBtn
  )
})
function resetFields() {
  const { isReset } = mergeResetBtn.value
  isReset && resetForm(hqFrom.value!)
  emit('reset')
}

/**
 * 提交按钮
 */
const mergeSubmitBtn = computed(() => {
  return Object.assign(
    { text: '提交', show: true, type: 'primary', size: 'small' },
    props.submitBtn
  )
})
async function onSubmit() {
  const pass = await submitForm(hqFrom.value!)
  if (pass) {
    const temp = toRaw(props.models)
    emit('submit', temp)
  } else {
    emit('error')
  }
}
</script>

<style scoped lang="scss">
.hq-form {
  width: 100%;
  display: flex;
  flex-direction: column;
  &_action {
    height: 30px;
    display: flex;
    align-items: center;
    padding-left: 120px;
  }
}
</style>
